package com.adou.service.impl;

import com.adou.common.mapper.*;
import com.adou.common.model.FlowDirection;
import com.adou.common.model.FlowMain;
import com.adou.common.model.FlowMainFile;
import com.adou.common.model.FlowTask;
import com.adou.common.util.EntityUtil;
import com.adou.common.util.StringUtil;
import com.adou.service.FlowDesignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class FlowDesignServiceImpl implements FlowDesignService {

    @Autowired
    private FlowDesignMapper flowDesignMapper;

    @Autowired
    private FlowMainMapper flowMainMapper;

    @Autowired
    private FlowTaskMapper flowTaskMapper;

    @Autowired
    private FlowDirectionMapper flowDirectionMapper;

    @Autowired
    private FlowMainFileMapper flowMainFileMapper;

    @Override
    @Transactional(readOnly = true)
    public EntityUtil.Entity queryData(Long fid) {
        Map<String, Object> map = new LinkedHashMap<>();

        FlowMain flowMain = new FlowMain();
        flowMain.setId(fid);
        List<FlowMain> flowMainList = flowMainMapper.find(flowMain);
        if (flowMainList != null && flowMainList.size() > 0) {
            flowMain = flowMainList.get(0);
        } else {
            return EntityUtil.error(101, "流程不存在");
        }
        map.put("title", flowMain.getCflowname());

        int initNum = 0;
        List<Map<String, Object>> nodeList = flowDesignMapper.queryNodeList(fid);
        Map<String, Object> nodeMap = new LinkedHashMap<>();
        if (nodeList.size() > 0) {
            for (Map<String, Object> m : nodeList) {
                initNum++;
                StringBuffer sb = new StringBuffer();
                if (StringUtil.isBlank(m.get("nodeId"))) {
                    sb.append(System.currentTimeMillis());
                } else {
                    sb.append(m.get("nodeId").toString());
                }
                m.put("width", Integer.parseInt(m.get("width").toString()));
                m.put("height", Integer.parseInt(m.get("height").toString()));
                m.put("top", Integer.parseInt(m.get("top").toString()));
                m.put("left", Integer.parseInt(m.get("left").toString()));
                nodeMap.put(sb.toString(), m);
            }
        }
        map.put("nodes", nodeMap);
        List<Map<String, Object>> lineList = flowDesignMapper.queryLineList(fid);
        Map<String, Object> lineMap = new LinkedHashMap<>();
        if (lineList.size() > 0) {
            for (Map<String, Object> m : lineList) {
                initNum++;
                StringBuffer sb = new StringBuffer();
                if (StringUtil.isBlank(m.get("lineId"))) {
                    sb.append(System.currentTimeMillis());
                } else {
                    sb.append(m.get("lineId").toString());
                }
                lineMap.put(sb.toString(), m);
            }
        }
        map.put("lines", lineMap);
        List<Map<String, Object>> areaList = flowDesignMapper.queryAreaList(fid);
        Map<String, Object> areaMap = new LinkedHashMap<>();
        if (areaList.size() > 0) {
            for (Map<String, Object> m : areaList) {
                initNum++;
                StringBuffer sb = new StringBuffer();
                if (StringUtil.isBlank(m.get("areaId"))) {
                    sb.append(System.currentTimeMillis());
                } else {
                    sb.append(m.get("areaId").toString());
                }
                areaMap.put(sb.toString(), m);
            }
        }
        map.put("areas", areaMap);
        map.put("initNum", initNum);
        return EntityUtil.success(map);
    }

    @Override
    @Transactional
    public EntityUtil.Entity insertData(Map<String, Object> map) {
        if (StringUtil.isBlank(map.get("fid"))) {
            return EntityUtil.error(201, "流程主键不存在");
        }
        String fid = map.get("fid").toString();

        FlowMain flowMain = new FlowMain();
        flowMain.setId(Long.parseLong(fid));
        List<FlowMain> flowMainList = flowMainMapper.find(flowMain);
        if (flowMainList == null) {
            return EntityUtil.error(202, "流程不存在");
        }

        FlowMainFile flowMainFile = new FlowMainFile();
        flowMainFile.setIfmid(Long.parseLong(fid));
        List<FlowMainFile> flowMainFileList = flowMainFileMapper.find(flowMainFile);
        if (flowMainFileList != null && flowMainFileList.size() > 0) {
            return EntityUtil.error(203, "流程已被使用，无法修改");
        }
        Map<String, Object> saveMap = new HashMap<>();
        Map<String, Object> nodeMap = (Map<String, Object>) map.get("nodes");
        Map<String, Object> lineMap = (Map<String, Object>) map.get("lines");

        if (nodeMap.isEmpty()) {
            return EntityUtil.error(204, "节点为空");
        }
        if (!checkBlr(nodeMap)) {
            return EntityUtil.error(205, "设置按区域或按部门办理，请选择办理人");
        }
        if (!checkTaskName(nodeMap)) {
            return EntityUtil.error(206, "节点名称存在空值，请填写节点名称");
        }
        if (lineMap.isEmpty()) {
            return EntityUtil.error(206, "未设置流程流向");
        }
        if (!checkStartNode("start round", nodeMap)) {
            return EntityUtil.error(207, "必须包含且只有一个开始节点！");
        }
        if (!checkCondition("bIsCondition", lineMap)) {
            return EntityUtil.error(208, "启用流转条件，请填写条件域名、条件比较符、条件值");
        }
        if (!checkCondition("bIsAndOr", lineMap)) {
            return EntityUtil.error(209, "启用下一流转条件，请填写条件域名1、条件比较符1、条件值1");
        }
        /**
         * 先清空流程，然后执行添加
         */
        flowDirectionMapper.deleteByIfmid(flowMainList);
        flowTaskMapper.deleteByIfmid(flowMainList);
        flowDesignMapper.deleteArea(Long.parseLong(fid));

        for (Map.Entry<String, Object> entry : nodeMap.entrySet()) {
            saveMap.clear();
            saveMap.put("nodeId", entry.getKey());
            Map<String, Object> m = (Map<String, Object>) entry.getValue();
            saveMap.putAll(m);
            FlowTask flowTask = new FlowTask();
            if (StringUtil.isNotBlank(saveMap.get("bIsAreaHandle"))) {
                flowTask.setbIsAreaHandle(Boolean.parseBoolean(saveMap.get("bIsAreaHandle").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsDepHandle"))) {
                flowTask.setbIsDepHandle(Boolean.parseBoolean(saveMap.get("bIsDepHandle").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsEdit"))) {
                flowTask.setbIsEdit(Boolean.parseBoolean(saveMap.get("bIsEdit").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsNotes"))) {
                flowTask.setbIsNotes(Boolean.parseBoolean(saveMap.get("bIsNotes").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsPrint"))) {
                flowTask.setbIsPrint(Boolean.parseBoolean(saveMap.get("bIsPrint").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsReturn"))) {
                flowTask.setbIsReturn(Boolean.parseBoolean(saveMap.get("bIsReturn").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsTel"))) {
                flowTask.setbIsTel(Boolean.parseBoolean(saveMap.get("bIsTel").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsTracing"))) {
                flowTask.setbIsTracing(Boolean.parseBoolean(saveMap.get("bIsTracing").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsMutiHandle"))) {
                flowTask.setbIsMutiHandle(Boolean.parseBoolean(saveMap.get("bIsMutiHandle").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsSign"))) {
                flowTask.setbIsSign(Boolean.parseBoolean(saveMap.get("bIsSign").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsSimpHandle"))) {
                flowTask.setbIsSimpHandle(Boolean.parseBoolean(saveMap.get("bIsSimpHandle").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("name"))) {
                flowTask.setCtaskname(saveMap.get("name").toString());
            }
            if (StringUtil.isNotBlank(saveMap.get("cconductids"))) {
                flowTask.setCconductids(saveMap.get("cconductids").toString());
            }
            if (StringUtil.isNotBlank(saveMap.get("cconductusers"))) {
                flowTask.setCconductusers(saveMap.get("cconductusers").toString());
            }
            if (StringUtil.isNotBlank(saveMap.get("cctrola"))) {
                flowTask.setCctrola(saveMap.get("cctrola").toString());
            }
            if (StringUtil.isNotBlank(saveMap.get("cctrolb"))) {
                flowTask.setCctrolb(saveMap.get("cctrolb").toString());
            }
            if (StringUtil.isNotBlank(saveMap.get("cctrolc"))) {
                flowTask.setCctrolc(saveMap.get("cctrolc").toString());
            }
            if (StringUtil.isNotBlank(saveMap.get("cctrold"))) {
                flowTask.setCctrold(saveMap.get("cctrold").toString());
            }
            if (StringUtil.isNotBlank(saveMap.get("ctasktype"))) {
                flowTask.setCtasktype(saveMap.get("ctasktype").toString());
            }
            flowTask.setIfmid(Long.parseLong(fid));
            flowDesignMapper.insertFlowTask(flowTask);
            saveMap.put("ftid", flowTask.getId());
            flowDesignMapper.insertNode(saveMap);
        }
        int i = 1;
        for (Map.Entry<String, Object> entry : lineMap.entrySet()) {
            saveMap.clear();
            saveMap.put("lineId", entry.getKey());
            Map<String, Object> m = (Map<String, Object>) entry.getValue();
            saveMap.putAll(m);

            FlowDirection flowDirection = new FlowDirection();
            flowDirection.setIfmid(Long.parseLong(fid));

            FlowTask flowTask;
            String from = saveMap.get("from").toString();
            flowTask = flowDesignMapper.queryFlowTaskByNodeId(from);
            flowDirection.setIstartftid(flowTask.getId());
            String to = saveMap.get("to").toString();
            flowTask = flowDesignMapper.queryFlowTaskByNodeId(to);
            flowDirection.setIendftid(flowTask.getId());

            if (StringUtil.isNotBlank(saveMap.get("name"))) {
                flowDirection.setCfdname(saveMap.get("name").toString());
            } else {
                flowDirection.setCfdname("line_" + i);
                i++;
            }
            if (StringUtil.isNotBlank(saveMap.get("iorder"))) {
                flowDirection.setIorder(Integer.parseInt(saveMap.get("iorder").toString()));
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsCondition")) && Boolean.parseBoolean(saveMap.get("bIsCondition").toString())) {
                flowDirection.setbIsCondition(Boolean.parseBoolean(saveMap.get("bIsCondition").toString()));
                flowDirection.setcFieldName(saveMap.get("cFieldName").toString());
                flowDirection.setcCompare(saveMap.get("cCompare").toString());
                flowDirection.setcValue(saveMap.get("cValue").toString());
            }
            if (StringUtil.isNotBlank(saveMap.get("bIsAndOr")) && Boolean.parseBoolean(saveMap.get("bIsAndOr").toString())) {
                flowDirection.setbIsAndOr(Boolean.parseBoolean(saveMap.get("bIsAndOr").toString()));
                flowDirection.setcOFieldName(saveMap.get("cOFieldName").toString());
                flowDirection.setcOCompare(saveMap.get("cOCompare").toString());
                flowDirection.setcOValue(saveMap.get("cOValue").toString());
            }
            flowDesignMapper.insertFlowDirection(flowDirection);

            saveMap.put("fdid", flowDirection.getId());
            flowDesignMapper.insertLine(saveMap);
        }
        Map<String, Object> areaMap = (Map<String, Object>) map.get("areas");
        if (!areaMap.isEmpty()) {
            for (Map.Entry<String, Object> entry : areaMap.entrySet()) {
                saveMap.clear();
                saveMap.put("fid", fid);
                saveMap.put("areaId", entry.getKey());
                Map<String, Object> m = (Map<String, Object>) entry.getValue();
                saveMap.putAll(m);
                flowDesignMapper.insertArea(saveMap);
            }
        }
        return EntityUtil.success();
    }

    /**
     * 检查节点名称
     *
     * @return
     */
    private static boolean checkTaskName(Map<String, Object> map) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Map<String, Object> m = (Map<String, Object>) entry.getValue();
            if (StringUtil.isBlank(m.get("name"))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 验证办理人
     *
     * @param map
     * @return
     */
    private static boolean checkBlr(Map<String, Object> map) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Map<String, Object> m = (Map<String, Object>) entry.getValue();
            if (StringUtil.isNotBlank(m.get("bIsDepHandle")) && Boolean.parseBoolean(m.get("bIsDepHandle").toString())) {
                if (StringUtil.isBlank(m.get("cconductids")) || StringUtil.isBlank(m.get("cconductusers"))) {
                    return false;
                }
            }
            if (StringUtil.isNotBlank(m.get("bIsAreaHandle")) && Boolean.parseBoolean(m.get("bIsAreaHandle").toString())) {
                if (StringUtil.isBlank(m.get("cconductids")) || StringUtil.isBlank(m.get("cconductusers"))) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 检查开始节点
     *
     * @return
     */
    private static boolean checkStartNode(String type, Map<String, Object> map) {
        int flag = 0;
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Map<String, Object> m = (Map<String, Object>) entry.getValue();
            if (m.get("type").toString().equals(type)) {
                flag++;
            }
        }
        if (flag != 1) {
            return false;
        }
        return true;
    }

    /**
     * 验证流转条件
     *
     * @param type
     * @param map
     * @return
     */
    private static boolean checkCondition(String type, Map<String, Object> map) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Map<String, Object> m = (Map<String, Object>) entry.getValue();
            if (type.equals("bIsCondition")) {
                if (StringUtil.isNotBlank(m.get("bIsCondition"))
                        && Boolean.parseBoolean(m.get("bIsCondition").toString())) {
                    if (StringUtil.isBlank(m.get("cFieldName"))
                            || StringUtil.isBlank(m.get("cCompare"))
                            || StringUtil.isBlank(m.get("cValue"))) {
                        return false;
                    }
                }
            }
            if (type.equals("bIsAndOr")) {
                if (StringUtil.isNotBlank(m.get("bIsAndOr"))
                        && Boolean.parseBoolean(m.get("bIsAndOr").toString())) {
                    if (StringUtil.isBlank(m.get("cOFieldName"))
                            || StringUtil.isBlank(m.get("cOCompare"))
                            || StringUtil.isBlank(m.get("cOValue"))) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

}
